home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / jcool01.zip / DATE_TIM.C < prev    next >
C/C++ Source or Header  |  1992-10-03  |  56KB  |  1,698 lines

  1. //
  2. // Copyright (C) 1991 Texas Instruments Incorporated.
  3. //
  4. // Permission is granted to any individual or institution to use, copy, modify,
  5. // and distribute this software, provided that this complete copyright and
  6. // permission notice is maintained, intact, in all copies and supporting
  7. // documentation.
  8. //
  9. // Texas Instruments Incorporated provides this software "as is" without
  10. // express or implied warranty.
  11. //
  12. //
  13. // Created: MBN 04/11/89 -- Initial design and implementation
  14. // Updated: MNF 07/25/89 -- Add the parse member function 
  15. // Updated: MBN 09/05/89 -- Added conditional exception handling
  16. // Updated: MBN 01/03/90 -- Adjusted strfind() calls to match new syntax
  17. // Updated: MBN 01/17/90 -- Fixed parsing algorithms to be GMT relative
  18. // Updated: MBN 02/06/90 -- Support years prior to the epoch (1/1/1970)
  19. // Updated: MBN 02/12/90 -- Changed all ascii() functions to return const char*
  20. // Updated: MBN 02/13/90 -- Made ascii_duration() a member function for epoch
  21. // Updated: MJF 03/12/90 -- Added group names to RAISE
  22. // Updated: MJF 01/17/91 -- Fixed parse to use ANSI function mktime()
  23. // Updated: DAN 01/21/91 -- Added adjust_dst() for OS/2 DST adjustment.
  24. // Updated: DLS 03/22/91 -- New lite version
  25. // Updated: JAM 08/12/92 -- removed DOS specifics, stdized #includes
  26. // Updated: JAM 08/12/92 -- added defs for static data members
  27. // Updated: JAM 08/12/92 -- removed timelocal()/mktime() defs (undid OS/2&SUN hacks)
  28. // Updated: JAM 10/03/92 -- removed "delete t" in funcs because ANSI C
  29. //                          localtime() returns pointer *static* |struct tm|
  30. //
  31. // This file  contains member and friend function  implementation  code for the
  32. // CoolDate_Time class defined  in the Date_Time.h header file.   Where appropriate
  33. // and possible, interfaces to,  and us of, existing  system functions has been
  34. // incorporated.  An overview  of the CoolDate_Time   class structor  along with  a
  35. // synopsis of each member and friend function, can be found in the Date_Time.h
  36. // header file.  Two static  char* tables are defined  within  this  file to be
  37. // used only by member functions of the CoolDate_Time class.  The first is the date
  38. // format table that is indexed by the enum  symbolic values in the <country.h>
  39. // header  file.  This table contains  format  strings for  sscanf()   used  to
  40. // implement the  formatted  ASCII  date output according  to  the rules of the
  41. // appropriate country.  The second is the time table that is  again indexed by
  42. // the enum symbolic values  in the <country.h> header  file and   performs the
  43. // same function for sscanf() output of the time.
  44. //
  45.  
  46. #ifndef DATETIMEH        // If DateTime class has not been defined
  47. #include <cool/Date_Time.h>    // Include class specification header file
  48. #endif
  49.  
  50. #include <ctype.h>        // ANSI C character macros
  51. #include <stdlib.h>        // Include standard c library support
  52.  
  53.  
  54. static int days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  55.  
  56. static const char* date_format_s[] = {        // Date formatting table
  57. "* UNKNOWN *",                    // Unknown country code
  58. "%02d-%02d-%4d",                // 03-29-1989 UNITED STATES   
  59. "%4d-%02d-%02d",                // 1989-29-03 FRENCH CANADIAN 
  60. "%02d-%02d/%4d",                // 03/29/1989 LATIN AMERICA   
  61. "%02d-%02d-%4d",                // 03-29-1989 NETHERLANDS     
  62. "%02d-%02d/%4d",                // 03/29/1989 BELGIUM         
  63. "%02d-%02d/%4d",                // 03/29/1989 FRANCE          
  64. "%02d-%02d/%4d",                // 03/29/1989 SPAIN           
  65. "%02d-%02d/%4d",                // 03/29/1989 ITALY           
  66. "%02d-%02d.%4d",                // 03.29.1989 SWITZERLAND     
  67. "%02d-%02d-%4d",                // 29-03-1989 UNITED KINGDOM  
  68. "%02d-%02d/%4d",                // 03/29/1989 DENMARK         
  69. "%4d-%02d-%02d",                // 1989-29-03 SWEDEN          
  70. "%02d/%02d/%4d",                // 03/29/1989 NORWAY          
  71. "%02d.%02d.%4d",                // 03.29.1989 GERMANY         
  72. "%02d/%02d/%4d",                // 03/29/1989 PORTUGAL        
  73. "%02d.%02d.%4d",                // 03.29.1989 FINLAND         
  74. "%02d/%02d/%4d",                // 03/29/1989 ARABIC COUNTRIES
  75. "%02d %02d %4d"                 // 03 29 1989 ISRAEL          
  76. };
  77.  
  78. static const char* time_format_s[] = {        // Time formatting table
  79. "* UNKNOWN *",                    // Unknown country code
  80. "%02d:%02d:%02d %s",                // 17:35:00 UNITED STATES   
  81. "%02d:%02d:%02d %s",                // 17:35:00 FRENCH CANADIAN 
  82. "%02d:%02d:%02d %s",                // 17:35:00 LATIN AMERICA   
  83. "%02d:%02d:%02d %s",                // 17:35:00 NETHERLANDS     
  84. "%02d:%02d:%02d %s",                // 17:35:00 BELGIUM         
  85. "%02d:%02d:%02d %s",                // 17:35:00 FRANCE          
  86. "%02d:%02d:%02d %s",                // 17:35:00 SPAIN           
  87. "%02d:%02d:%02d %s",                // 17:35:00 ITALY           
  88. "%02d.%02d.%02d %s",                // 17.35.00 SWITZERLAND     
  89. "%02d:%02d:%02d %s",                // 17:35:00 UNITED KINGDOM  
  90. "%02d:%02d:%02d %s",                // 17:35:00 DENMARK         
  91. "%02d.%02d.%02d %s",                // 17.35.00 SWEDEN          
  92. "%02d:%02d:%02d %s",                // 17:35:00 NORWAY          
  93. "%02d.%02d.%02d %s",                // 17.35.00 GERMANY         
  94. "%02d:%02d:%02d %s",                // 17:35:00 PORTUGAL        
  95. "%02d.%02d.%02d %s",                // 17.35.00 FINLAND         
  96. "%02d:%02d:%02d %s",                // 17:35:00 ARABIC COUNTRIES
  97. "%02d:%02d:%02d %s"                // 17:35:00 ISRAEL          
  98. };
  99.  
  100. #define TIME_VALUES this->dt.tm_hour, this->dt.tm_min, this->dt.tm_sec, \
  101.         tz_table[this->tz_code]
  102. #define MONTH_DATE_VALUES this->dt.tm_mon+1, this->dt.tm_mday, \
  103.         this->get_year (), tz_table[this->tz_code]
  104. #define DATE_MONTH_VALUES this->dt.tm_mday, this->dt.tm_mon+1, \
  105.         this->get_year (), tz_table[this->tz_code]
  106. #define YEAR_MONTH_VALUES this->get_year(), this->dt.tm_mday, \
  107.             this->dt.tm_mon+1, tz_table[this->tz_code]
  108.  
  109. // default_tz_code_s -- Default time zone
  110. time_zone CoolDate_Time::default_tz_code_s;
  111.  
  112. // default_c_code_s -- Default country
  113. country CoolDate_Time::default_c_code_s;
  114.  
  115. // adjust_tz -- Calculate adjustment for time zone from GMT in seconds
  116. // Input:       None
  117. // Output:      None
  118.  
  119. void CoolDate_Time::adjust_tz () {
  120.   long local_secs = 0;
  121.   tm* t;                    // Temporary variable
  122.   long sys_seconds = time ((long*)0);        // System GMT time in seconds
  123.   set_tz (this->tz_code);            // Setup local time conversion
  124.   t = localtime (&sys_seconds);            // Convert to local time
  125.   for (int i = 70; i < t->tm_year; i++) {
  126.     local_secs += (YEAR + DAY);
  127.     if (IS_LEAP_YEAR (i)) local_secs += DAY;
  128.   }
  129.   for (i = 0; i < t->tm_mon; i++) {
  130.     local_secs += (DAY * days_in_month[i]);
  131.     if (i == FEBRUARY && IS_LEAP_YEAR (t->tm_year))
  132.       local_secs += DAY;
  133.   }
  134.   t->tm_mday--;
  135.   local_secs += (DAY * t->tm_mday);
  136.   local_secs += (HOUR * t->tm_hour);
  137.   local_secs += (MINUTE * t->tm_min);
  138.   local_secs += t->tm_sec;
  139.   this->time_adjust = sys_seconds - local_secs; // TZ offset in seconds
  140. }
  141.  
  142.  
  143. // adjust_year -- Calculate offset from epoch to support years before 1/1/1970
  144. // Input:         None
  145. // Output:        None
  146. //
  147. // The CoolDate_Time class is  based upon the ANSI  C time(2) function. This
  148. // calculates time/date in seconds since the  epoch (1/1/1970). To allow
  149. // the CoolDate_Time class to support dates before the epoch we need to find
  150. // which year  after 1970 has the same  day of week/dates correlation as
  151. // the one specified. To determine this, we make use of the  fact that a
  152. // yearly periodic cycle of 28 years exists such that 1/1/1970 fell on a
  153. // Thursday and 1/1/1998 is also a Thursday.
  154. //
  155.  
  156. void CoolDate_Time::adjust_year (long& year) {
  157.   if (year > 99 && year < 1970) {
  158.     this->year_adjust = int(1970 - year);
  159.     year += NEW_YEAR (this->year_adjust);
  160.   }
  161.   else if (year < 70) {
  162.     this->year_adjust = int(70 - year);
  163.     year += NEW_YEAR (this->year_adjust);
  164.   }
  165.   else
  166.     this->year_adjust = 0;
  167. }
  168.  
  169.  
  170. // set_tz -- Set the local time zone before conversion
  171. //           of object from GMT seconds to tm structure
  172. // Input:    Time zone
  173. // Output:   None
  174.  
  175. void set_tz (time_zone tz) {
  176.   char tz_name[50];                // Temporary variable
  177.   strcpy (tz_name, "TZ=");            // TZ envionmental symbol
  178.   strcpy (&tz_name[3], tz_table[tz]);        // Concatenate time zone name
  179.   putenv (tz_name);                // Set environment TZ variable
  180. }
  181.  
  182.  
  183. // resolve -- This private method takes a long representing the
  184. //            number of seconds since 01/01/1970 00:00:00 GMT
  185. //            and converts that into local time, placing the 
  186. //            result into the date/time structure
  187. // Input:     this*
  188. // Output:    None -- date/time structure updated
  189.  
  190. void CoolDate_Time::resolve () {
  191.   tm* t;                    // Temporary variable
  192.   set_tz (this->tz_code);            // Set local time zone
  193.   adjust_tz ();                    // Calculate time zone offset
  194.   t = localtime (&(this->time_seconds));    // Convert to local time zone
  195.   this->dt.tm_sec = t->tm_sec;            // Copy seconds value
  196.   this->dt.tm_min = t->tm_min;            // Copy minutes value
  197.   this->dt.tm_hour = t->tm_hour;        // Copy hours value
  198.   this->dt.tm_mday = t->tm_mday;        // Copy day of month value
  199.   this->dt.tm_mon = t->tm_mon;            // Copy month value
  200.   this->dt.tm_year = t->tm_year;        // Copy year value
  201.   this->dt.tm_wday = t->tm_wday;        // Copy day of week value
  202.   this->dt.tm_yday = t->tm_yday;        // Copy day of year value
  203.   this->dt.tm_isdst = t->tm_isdst;        // Copy day light savings flag
  204. }
  205.  
  206.  
  207. // CoolDate_Time() -- Simple constructor for empty CoolDate_Time object
  208. // Input:         None
  209. // Output:        CoolDate_Time reference
  210.  
  211. CoolDate_Time::CoolDate_Time () {
  212.   this->time_seconds = time((long*)0);        // Zero seconds
  213. #ifdef ERROR_CHECKING
  214.   if (this->default_c_code_s == NULL) {        // If no country code set
  215.     //RAISE (Warning, SYM(CoolDate_Time), SYM(No_C_Code),
  216.     printf ("CoolDate_Time::CoolDate_Time(): Default country code not set but used.\n");
  217.   }
  218.   if (this->default_tz_code_s == NULL) {    // If no time zone code set
  219.     //RAISE (Warning, SYM(CoolDate_Time), SYM(No_Tz_Code),
  220.     printf ("CoolDate_Time::CoolDate_Time(): Default time zone code not set but used.\n");
  221.   }
  222. #endif
  223.   this->c_code = this->default_c_code_s;    // Set country code
  224.   this->tz_code = this->default_tz_code_s;    // Set time zone code
  225.   set_tz (default_tz_code_s);            // Set local time zone
  226. }
  227.  
  228.  
  229. // CoolDate_Time(tz,c) -- Simple constructor for empty CoolDate_Time object
  230. //                    that also sets the time zone and country
  231. // Input:             Time zone, country codes
  232. // Output:            CoolDate_Time reference
  233.  
  234. CoolDate_Time::CoolDate_Time (time_zone tz, country c) {
  235.   this->time_seconds = time((long*)0);        // Zero seconds
  236.   this->c_code = c;                // Set country code
  237.   this->tz_code = tz;                // Set time zone code
  238.   set_tz (tz);                    // Set local time zone
  239. }
  240.  
  241.  
  242. // CoolDate_Time(const CoolDate_Time&) -- Constructor to duplicate a CoolDate_Time object
  243. // Input:                        CoolDate_Time reference
  244. // Output:                       CoolDate_Time reference
  245.  
  246. CoolDate_Time::CoolDate_Time (const CoolDate_Time& d) {
  247.   this->time_seconds = d.time_seconds;
  248.   this->tz_code = d.tz_code;
  249.   this->c_code = d.c_code;
  250.   this->dt.tm_sec = d.dt.tm_sec;
  251.   this->dt.tm_min = d.dt.tm_min;
  252.   this->dt.tm_hour = d.dt.tm_hour;
  253.   this->dt.tm_mday = d.dt.tm_mday;
  254.   this->dt.tm_mon = d.dt.tm_mon;
  255.   this->dt.tm_year = d.dt.tm_year;
  256.   this->dt.tm_wday = d.dt.tm_wday;
  257.   this->dt.tm_yday = d.dt.tm_yday;
  258.   this->dt.tm_isdst = d.dt.tm_isdst;
  259.   this->time_adjust = d.time_adjust;
  260.   this->year_adjust = d.year_adjust;
  261.   this->century = d.century;
  262. }
  263.  
  264.  
  265. // ~CoolDate_Time -- CoolDate_Time class destructor
  266. // Input:        this*
  267. // Output:       None
  268.  
  269. CoolDate_Time::~CoolDate_Time () { 
  270. }
  271.                        
  272.  
  273. // set_local_time -- Sets the time zone and DST adjusted local time
  274. // Input:            this*
  275. // Output:           CoolDate_Time reference with slots updated for local time
  276.  
  277. void CoolDate_Time::set_local_time () {
  278.   tm* t;                    // Temporary pointer variable
  279.   long sys_seconds = time ((long*)0);        // System GMT time in seconds
  280.   this->time_seconds = sys_seconds;        // Save time for future use
  281.   set_tz (this->tz_code);            // Setup local time conversion
  282.   t = localtime (&sys_seconds);            // Convert secs to local time
  283.   this->dt.tm_sec = t->tm_sec;            // Copy seconds value
  284.   this->dt.tm_min = t->tm_min;            // Copy minutes value
  285.   this->dt.tm_hour = t->tm_hour;        // Copy hours value
  286.   this->dt.tm_mday = t->tm_mday;        // Copy day of month value
  287.   this->dt.tm_mon = t->tm_mon;            // Copy month value
  288.   this->dt.tm_year = t->tm_year;        // Copy year value
  289.   this->dt.tm_wday = t->tm_wday;        // Copy day of week value
  290.   this->dt.tm_yday = t->tm_yday;        // Copy day of year value
  291.   this->dt.tm_isdst = t->tm_isdst;        // Copy day light savings flag
  292.   this->year_adjust = 0;
  293.   this->century = 1900;
  294. }
  295.  
  296.  
  297. // set_gm_time -- Set the Greenwich Mean Time
  298. // Input:         this*
  299. // Output:        CoolDate_Time reference with slots updated for GMT
  300.  
  301. void CoolDate_Time::set_gm_time () {
  302.   tm* t;                    // Temporary pointer variable
  303.   long sys_seconds = time ((long*)0);        // System GMT time in seconds
  304.   this->tz_code = GB_EIRE;            // GMT time zone
  305.   set_tz (this->tz_code);            // Setup GMT conversion
  306.   t = localtime (&sys_seconds);            // Convert seconds to local time
  307.   this->dt.tm_sec = t->tm_sec;            // Copy seconds value
  308.   this->dt.tm_min = t->tm_min;            // Copy minutes value
  309.   this->dt.tm_hour = t->tm_hour;        // Copy hours value
  310.   this->dt.tm_mday = t->tm_mday;        // Copy day of month value
  311.   this->dt.tm_mon = t->tm_mon;            // Copy month value
  312.   this->dt.tm_year = t->tm_year;        // Copy year value
  313.   this->dt.tm_wday = t->tm_wday;        // Copy day of week value
  314.   this->dt.tm_yday = t->tm_yday;        // Copy day of year value
  315.   this->dt.tm_isdst = t->tm_isdst;        // Copy day light savings flag
  316.   this->year_adjust = 0;
  317.   this->century = 1900;
  318. }
  319.  
  320.  
  321. // operator= -- Assignment operator to duplicate a CoolDate_Time object
  322. // Input:       CoolDate_Time reference
  323. // Output:      CoolDate_Time reference
  324.  
  325. CoolDate_Time& CoolDate_Time::operator= (const CoolDate_Time& d) {
  326.   this->time_seconds = d.time_seconds;
  327.   this->tz_code = d.tz_code;
  328.   this->c_code = d.c_code;
  329.   this->dt.tm_sec = d.dt.tm_sec;
  330.   this->dt.tm_min = d.dt.tm_min;
  331.   this->dt.tm_hour = d.dt.tm_hour;
  332.   this->dt.tm_mday = d.dt.tm_mday;
  333.   this->dt.tm_mon = d.dt.tm_mon;
  334.   this->dt.tm_year = d.dt.tm_year;
  335.   this->dt.tm_wday = d.dt.tm_wday;
  336.   this->dt.tm_yday = d.dt.tm_yday;
  337.   this->dt.tm_isdst = d.dt.tm_isdst;
  338.   this->time_adjust = d.time_adjust;
  339.   this->year_adjust = d.year_adjust;
  340.   this->century = d.century;
  341.   return *this;
  342. }
  343.  
  344.  
  345. // operator+= -- Add a time interval to a CoolDate_Time object, assign
  346. //               the result, and update the tm structure
  347. // Input:        "n" seconds representing time interval
  348. // Output:       CoolDate_Time reference
  349.  
  350. CoolDate_Time& CoolDate_Time::operator+= (long n) {
  351.   this->time_seconds += n;
  352.   this->resolve ();
  353.   return (*this);
  354. }
  355.  
  356.  
  357. // operator-= -- Subtract a time interval from a CoolDate_Time object,
  358. //               assign the result, and update the tm structure
  359. // Input:        "n" seconds representing time interval
  360. // Output:       CoolDate_Time reference
  361.  
  362. CoolDate_Time& CoolDate_Time::operator-= (long n) {
  363.   this->time_seconds -= n;
  364.   this->resolve ();
  365.   return (*this);
  366. }
  367.  
  368.  
  369. // operator>> -- Input CoolDate_Time object from input stream. If a time zone is
  370. //               also entered, it will be set too.
  371. // Input:        Input stream reference, CoolDate_Time reference
  372. // Output:       CoolDate_Time reference
  373.  
  374. istream& operator>> (istream& is, CoolDate_Time& d) {
  375.   char* s = "";                    // Temporary pointer
  376.   is.get(s,256);                // Read upto 256 characters
  377.   d.parse(s,1);                    // Parse input string
  378.   return is;                    // Return stream object
  379. }
  380.  
  381.  
  382. // incr_sec -- Advance Date/Time by "n" second(s)
  383. // Input:      Number of seconds to advance (default 1)
  384. // Output:     None -- CoolDate_Time object updated 
  385.  
  386. void CoolDate_Time::incr_sec (int n) {
  387.   this->time_seconds += n;
  388.   this->resolve ();
  389. }
  390.  
  391.  
  392. // incr_min -- Advance Date/Time by "n" minute(s)
  393. // Input:      Number of minutes to advance (default 1)
  394. // Output:     None -- CoolDate_Time object updated 
  395.  
  396. void CoolDate_Time::incr_min (int n) {
  397.   this->time_seconds += (MINUTE * n);
  398.   this->resolve ();
  399. }
  400.  
  401.  
  402. // incr_hour -- Advance Date/Time by "n" hour(s)
  403. // Input:       Number of hours to advance (default 1)
  404. // Output:      None -- CoolDate_Time object updated 
  405.  
  406. void CoolDate_Time::incr_hour (int n) {
  407.   this->time_seconds += (HOUR * n);
  408.   this->resolve ();
  409. }
  410.  
  411.  
  412. // incr_day -- Advance Date/Time by "n" day(s)
  413. // Input:      Number of days to advance (default 1)
  414. // Output:     None -- CoolDate_Time object updated 
  415.  
  416. void CoolDate_Time::incr_day (int n) {
  417.   this->time_seconds += (DAY * n);
  418.   this->resolve ();
  419. }
  420.  
  421.  
  422. // incr_week -- Advance Date/Time by "n" week(s)
  423. // Input:       Number of weeks to advance (default 1)
  424. // Output:      None -- CoolDate_Time object updated 
  425.  
  426. void CoolDate_Time::incr_week (int n) {
  427.   this->time_seconds += (WEEK * n);
  428.   this->resolve ();
  429. }
  430.  
  431.  
  432. // incr_month -- Advance Date/Time by "n" month(s)
  433. // Input:        Number of months to advance (default 1)
  434. // Output:       None -- CoolDate_Time object updated
  435.  
  436. void CoolDate_Time::incr_month (int n) {
  437.   int temp_year = this->dt.tm_year;
  438.   int temp_month = this->dt.tm_mon;
  439.   for (int i = 0; i < n; i++, temp_month++) {
  440.     if (temp_month > DECEMBER) {
  441.       temp_month = JANUARY;
  442.       temp_year++;
  443.     }
  444.     time_seconds += (DAY * days_in_month[temp_month]);
  445.     if (temp_month == FEBRUARY && IS_LEAP_YEAR (temp_year))
  446.       time_seconds += DAY;
  447.   }
  448.   this->resolve ();
  449. }
  450.  
  451.  
  452. // incr_year -- Advance Date/Time by "n" year(s)
  453. // Input:       Number of years to advance (default 1)
  454. // Output:      None -- CoolDate_Time object updated 
  455.  
  456. void CoolDate_Time::incr_year (int n) {
  457.   int temp_year = this->dt.tm_year;
  458.   for (int i = 0; i < n; i++, temp_year++) {
  459.     time_seconds += (YEAR+DAY);
  460.     if ((IS_LEAP_YEAR (temp_year) && (this->dt.tm_mon < FEBRUARY || 
  461.     (this->dt.tm_mon == FEBRUARY && this->dt.tm_mday != 29))) ||
  462.     (IS_LEAP_YEAR (temp_year+1) && this->dt.tm_mon > FEBRUARY))
  463.       time_seconds += DAY;
  464.   }
  465.   this->resolve ();
  466. }
  467.  
  468.  
  469. // decr_month -- Retreat Date/Time by "n" month(s)
  470. // Input:        Number of months to retreat (default 1)
  471. // Output:       None -- CoolDate_Time object updated
  472.  
  473. void CoolDate_Time::decr_month (int n) {
  474.   int temp_year = this->dt.tm_year;
  475.   int temp_month = this->dt.tm_mon;
  476.   for (int i = 0; i < n; i++, temp_month--) {
  477.     if (temp_month < JANUARY) {
  478.       temp_month = DECEMBER;
  479.       temp_year--;
  480.     }
  481.     time_seconds -= (DAY * days_in_month[temp_month]);
  482.     if (temp_month == FEBRUARY && IS_LEAP_YEAR (temp_year))
  483.       time_seconds -= DAY;
  484.   }
  485.   this->resolve ();
  486. }
  487.  
  488.  
  489. // decr_year -- Retreat Date/Time by "n" year(s)
  490. // Input:       Number of years to retreat (default 1)
  491. // Output:      None -- CoolDate_Time object updated 
  492.  
  493. void CoolDate_Time::decr_year (int n) {
  494.   int temp_year = this->dt.tm_year;
  495.   for (int i = 0; i < n; i++, temp_year--) {
  496.     time_seconds -= (YEAR+DAY);
  497.     if ((IS_LEAP_YEAR (temp_year) && (this->dt.tm_mon > FEBRUARY ||
  498.     (this->dt.tm_mon == FEBRUARY && this->dt.tm_mday == 29))) ||
  499.     (IS_LEAP_YEAR (temp_year-1) && this->dt.tm_mon <= FEBRUARY))
  500.       time_seconds -= DAY;
  501.   }
  502.   this->resolve ();
  503. }
  504.  
  505.  
  506. // start_min -- Increment CoolDate_Time object to start of "n" minutes
  507. // Input:       Number of minutes to advance to start (default 1)
  508. //              where time is set to HH:MM:00
  509. // Output:      None -- CoolDate_Time object updated
  510.  
  511. void CoolDate_Time::start_min (int n) {
  512.   this->time_seconds += (MINUTE - this->dt.tm_sec);
  513.   incr_min (n-1);
  514. }
  515.  
  516.  
  517. // end_min -- Increment CoolDate_Time object to end of "n" minutes
  518. //            time is set to HH:MM:59
  519. // Input:     Number of minutes to advance to end (default 1)
  520. // Output:    None -- CoolDate_Time object updated
  521.  
  522. void CoolDate_Time::end_min (int n) {
  523.   this->time_seconds += (MINUTE - this->dt.tm_sec -1);
  524.   incr_min (n-1);
  525. }
  526.  
  527.  
  528. // start_hour -- Increment CoolDate_Time object to start of "n" hours
  529. // Input:        Number of hours to advance to start (default 1)
  530. //               where time is set to HH:00:00
  531. // Output:       None -- CoolDate_Time object updated
  532.  
  533. void CoolDate_Time::start_hour (int n) {
  534.   this->time_seconds += (MINUTE - this->dt.tm_sec);
  535.   this->time_seconds += (HOUR - (this->dt.tm_min * MINUTE) - MINUTE);
  536.   incr_hour (n-1);
  537. }
  538.  
  539.  
  540. // end_hour --   Increment CoolDate_Time object to end of "n" hours
  541. //               time is set to HH:59:59
  542. // Input:        Number of hours to advance to end (default 1)
  543. // Output:       None -- CoolDate_Time object updated
  544.  
  545. void CoolDate_Time::end_hour (int n) {
  546.   this->time_seconds += (MINUTE - this->dt.tm_sec - 1);
  547.   this->time_seconds += (HOUR - (this->dt.tm_min * MINUTE) - MINUTE);
  548.   incr_hour (n-1);
  549. }
  550.  
  551.  
  552. // start_day -- Increment CoolDate_Time object to start of "n" days
  553. //              time set to 00:00:00
  554. // Input:       Number of days to advance to start (default 1)
  555. // Output:      None -- CoolDate_Time object updated
  556.  
  557. void CoolDate_Time::start_day (int n) {
  558.   this->time_seconds += (MINUTE - this->dt.tm_sec);
  559.   this->time_seconds += (HOUR - (this->dt.tm_min * MINUTE) - MINUTE);
  560.   this->time_seconds += (DAY - (this->dt.tm_hour * HOUR) - HOUR);
  561.   incr_day (n-1);
  562. }
  563.  
  564.  
  565. // end_day -- Increment CoolDate_Time object to end of "n" days
  566. //            time set to 23:59:59
  567. // Input:     Number of days to advance to end (default 1)
  568. // Output:    None -- CoolDate_Time object updated
  569.  
  570. void CoolDate_Time::end_day (int n) {
  571.   this->time_seconds += (MINUTE - this->dt.tm_sec - 1);
  572.   this->time_seconds += (HOUR - (this->dt.tm_min * MINUTE) - MINUTE);
  573.   this->time_seconds += (DAY - (this->dt.tm_hour * HOUR) - HOUR);
  574.   incr_day (n-1);
  575. }
  576.  
  577.  
  578. // start_week -- Increment CoolDate_Time object to start of "n" weeks
  579. //               Date/time set to Monday 00:00:00
  580. // Input:        Number of weeks to advance to start (default 1)
  581. // Output:       None -- CoolDate_Time object updated
  582.  
  583. void CoolDate_Time::start_week (int n) {
  584.   this->time_seconds += (MINUTE - this->dt.tm_sec);
  585.   this->time_seconds += (HOUR - (this->dt.tm_min * MINUTE) - MINUTE);
  586.   this->time_seconds += (DAY - (this->dt.tm_hour * HOUR) - HOUR);
  587.   this->time_seconds += (WEEK - (this->dt.tm_wday * DAY));
  588.   this->time_seconds += DAY;
  589.   incr_week (n-1);
  590. }
  591.  
  592.  
  593. // end_week -- Increment CoolDate_Time object to end of "n" weeks
  594. //             Date/Time set to Sunday 23:59:59
  595. // Input:      Number of weeks to advance to end (default 1)
  596. // Output:     None -- CoolDate_Time object updated
  597.  
  598. void CoolDate_Time::end_week (int n) {
  599.   this->time_seconds += (MINUTE - this->dt.tm_sec - 1);
  600.   this->time_seconds += (HOUR - (this->dt.tm_min * MINUTE) - MINUTE);
  601.   this->time_seconds += (DAY - (this->dt.tm_hour * HOUR) - HOUR);
  602.   this->time_seconds += (WEEK - (this->dt.tm_wday * DAY) - DAY);
  603.   this->time_seconds += DAY;
  604.   incr_week (n-1);
  605. }
  606.  
  607.  
  608. // start_month -- Increment CoolDate_Time object to start of "n" months
  609. //                Date/time set to 01/MM/YYYY 00:00:00
  610. // Input:         Number of months to advance to start (default 1)
  611. // Output:        None -- CoolDate_Time object updated
  612.  
  613. void CoolDate_Time::start_month (int n) {
  614.   int temp_day = this->dt.tm_mday;        // Date in month
  615.   int temp_month = this->dt.tm_mon;        // Current month
  616.   this->time_seconds += (MINUTE - this->dt.tm_sec);
  617.   this->time_seconds += (HOUR - (this->dt.tm_min * MINUTE) - MINUTE);
  618.   this->time_seconds += (DAY - (this->dt.tm_hour * HOUR) - HOUR);
  619.   for ( ; temp_day < days_in_month[temp_month]; temp_day++)
  620.     this->time_seconds += DAY;
  621.   if (temp_month == FEBRUARY && IS_LEAP_YEAR (this->dt.tm_year))
  622.     this->time_seconds += DAY;
  623.   incr_month (n-1);
  624. }
  625.  
  626.  
  627. // end_month -- Increment CoolDate_Time object to end of "n" months
  628. //              Date/time set to 31/MM/YYYY 23:59:59
  629. // Input:       Number of months to advance to end (default 1)
  630. // Output:      None -- CoolDate_Time obejct updated
  631.  
  632. void CoolDate_Time::end_month (int n) {
  633.   int temp_day = this->dt.tm_mday;        // Date in month
  634.   int temp_month = this->dt.tm_mon;        // Current month
  635.   this->time_seconds += (MINUTE - this->dt.tm_sec - 1);
  636.   this->time_seconds += (HOUR - (this->dt.tm_min * MINUTE) - MINUTE);
  637.   this->time_seconds += (DAY - (this->dt.tm_hour * HOUR) - HOUR);
  638.   for ( ; temp_day < days_in_month[temp_month]; temp_day++)
  639.     this->time_seconds += DAY;
  640.   if (temp_month == FEBRUARY && IS_LEAP_YEAR (this->dt.tm_year))
  641.     this->time_seconds += DAY;
  642.   incr_month (n-1);
  643. }
  644.  
  645.  
  646. // start_year -- Increment CoolDate_Time object to start of "n" years
  647. //               Date/Time set to 01/01/YYYY 00:00:00
  648. // Input:        Number of years to advance to start (default 1)
  649. // Output:       None -- CoolDate_Time object updated
  650.  
  651. void CoolDate_Time::start_year (int n) {
  652.   int temp_year = this->dt.tm_year;
  653.   int temp_day = this->dt.tm_mday;        // Date in month
  654.   int temp_month = this->dt.tm_mon;        // Current month
  655.   this->time_seconds += (MINUTE - this->dt.tm_sec);
  656.   this->time_seconds += (HOUR - (this->dt.tm_min * MINUTE) - MINUTE);
  657.   this->time_seconds += (DAY - (this->dt.tm_hour * HOUR) - HOUR);
  658.   this->time_seconds += HOUR;
  659.   for ( ; temp_day < days_in_month[temp_month]; temp_day++)
  660.     this->time_seconds += DAY;
  661.   if (temp_month == FEBRUARY && IS_LEAP_YEAR (temp_year))
  662.     this->time_seconds += DAY;
  663.   for (++temp_month; temp_month <= DECEMBER; temp_month++) {
  664.     this->time_seconds += (DAY * days_in_month[temp_month]);
  665.     if (temp_month == FEBRUARY && IS_LEAP_YEAR (temp_year))
  666.       time_seconds += DAY;
  667.   }
  668.   incr_year (n-1);
  669. }
  670.   
  671.  
  672. // end_year -- Increment CoolDate_Time object to end of "n" years
  673. //             Date/time set to 31/12/YYYY 23:59:59
  674. // Input:      Number of years to advance to end (default 1)
  675. // Output:     None -- CoolDate_Time object updated
  676.  
  677. void CoolDate_Time::end_year (int n) {
  678.   int temp_year = this->dt.tm_year;
  679.   int temp_day = this->dt.tm_mday;        // Date in month
  680.   int temp_month = this->dt.tm_mon;        // Current month
  681.   this->time_seconds += (MINUTE - this->dt.tm_sec - 1);
  682.   this->time_seconds += (HOUR - (this->dt.tm_min * MINUTE) - MINUTE);
  683.   this->time_seconds += (DAY - (this->dt.tm_hour * HOUR) - HOUR);
  684.   this->time_seconds += HOUR;
  685.   for ( ; temp_day < days_in_month[temp_month]; temp_day++)
  686.     this->time_seconds += DAY;
  687.   if (temp_month == FEBRUARY && IS_LEAP_YEAR (temp_year))
  688.     this->time_seconds += DAY;
  689.   for (++temp_month; temp_month <= DECEMBER; temp_month++) {
  690.     this->time_seconds += (DAY * days_in_month[temp_month]);
  691.     if (temp_month == FEBRUARY && IS_LEAP_YEAR (temp_year))
  692.       time_seconds += DAY;
  693.   }
  694.   incr_year (n-1);
  695. }
  696.  
  697.  
  698. // ascii_time -- Returns the time in ASCII format for the country
  699. //               indicated in the CoolDate_Time object. Note that the
  700. //               storage is static and destroyed on the next call.
  701. // Input:        this*
  702. // Output:       Formatted char* string
  703.  
  704. const char* CoolDate_Time::ascii_time () const {
  705.   static char storage_s[35];
  706.   switch (this->c_code) {
  707.  
  708.   case UNKNOWN_COUNTRY:
  709.     sprintf (storage_s, time_format_s[UNKNOWN_COUNTRY]);
  710.     break;
  711.  
  712.   case UNITED_STATES:
  713.   case NORWAY:
  714.   case GERMANY:
  715.   case PORTUGAL:
  716.   case FINLAND:
  717.   case ARABIC_COUNTRIES:
  718.   case ISRAEL:
  719.   case LATIN_AMERICA:
  720.   case NETHERLANDS:
  721.   case BELGIUM:
  722.   case FRANCE:
  723.   case SPAIN:
  724.   case ITALY:
  725.   case SWITZERLAND:
  726.   case DENMARK:
  727.   case UNITED_KINGDOM:
  728.   case SWEDEN:
  729.   case FRENCH_CANADIAN:
  730.     sprintf (storage_s, time_format_s[this->c_code], TIME_VALUES);
  731.     break;
  732.   }
  733.   return storage_s;
  734. }
  735.  
  736.  
  737. // ascii_date -- Returns the date in ASCII format for the country
  738. //               indicated in the CoolDate_Time object. Note that the
  739. //               storage is static and destroyed on the next call.
  740. // Input:        this*
  741. // Output:       Formatted char* string
  742.  
  743. const char* CoolDate_Time::ascii_date () const {
  744.   static char storage_s[11];
  745.   switch (this->c_code) {
  746.  
  747.   case UNKNOWN_COUNTRY:
  748.     sprintf (storage_s, date_format_s[UNKNOWN_COUNTRY]);
  749.     break;
  750.  
  751.   case UNITED_STATES:
  752.   case NORWAY:
  753.   case GERMANY:
  754.   case PORTUGAL:
  755.   case FINLAND:
  756.   case ARABIC_COUNTRIES:
  757.   case ISRAEL:
  758.   case LATIN_AMERICA:
  759.   case NETHERLANDS:
  760.   case BELGIUM:
  761.   case FRANCE:
  762.   case SPAIN:
  763.   case ITALY:
  764.   case SWITZERLAND:
  765.   case DENMARK:
  766.     sprintf (storage_s, date_format_s[this->c_code], MONTH_DATE_VALUES);
  767.     break;
  768.  
  769.   case UNITED_KINGDOM:
  770.     sprintf (storage_s, date_format_s[this->c_code], DATE_MONTH_VALUES);
  771.     break;
  772.  
  773.   case SWEDEN:
  774.   case FRENCH_CANADIAN:
  775.     sprintf (storage_s, date_format_s[this->c_code], YEAR_MONTH_VALUES);
  776.     break;
  777.   }
  778.   return storage_s;
  779. }
  780.  
  781.  
  782. // ascii_date_time -- Returns date and time in ASCII format for
  783. //                    country indicated in CoolDate_Time object. Note
  784. //                    that the storage is static and destroyed 
  785. //                    on the next call
  786. // Input:             this*
  787. // Output:            Formatted char* string
  788.  
  789. const char* CoolDate_Time::ascii_date_time () const {
  790.   static char storage_s[50];            // String to hold output
  791.   switch (this->c_code) {
  792.  
  793.   case UNKNOWN_COUNTRY:
  794.     sprintf (storage_s, date_format_s[UNKNOWN_COUNTRY]);
  795.  
  796.   case UNITED_STATES:
  797.   case NORWAY:
  798.   case GERMANY:
  799.   case PORTUGAL:
  800.   case FINLAND:
  801.   case ARABIC_COUNTRIES:
  802.   case ISRAEL:
  803.   case LATIN_AMERICA:
  804.   case NETHERLANDS:
  805.   case BELGIUM:
  806.   case FRANCE:
  807.   case SPAIN:
  808.   case ITALY:
  809.   case SWITZERLAND:
  810.   case DENMARK:
  811.     sprintf (storage_s, date_format_s[this->c_code], MONTH_DATE_VALUES);
  812.     storage_s[10] = ' ';
  813.     sprintf (&storage_s[11], time_format_s[this->c_code], TIME_VALUES);
  814.     break;
  815.  
  816.   case UNITED_KINGDOM:
  817.     sprintf (storage_s, date_format_s[this->c_code], DATE_MONTH_VALUES);
  818.     storage_s[10] = ' ';
  819.     sprintf (&storage_s[11], time_format_s[this->c_code], TIME_VALUES);
  820.     break;
  821.  
  822.   case SWEDEN:
  823.   case FRENCH_CANADIAN:
  824.     sprintf (storage_s, date_format_s[this->c_code], YEAR_MONTH_VALUES);
  825.     storage_s[10] = ' ';
  826.     sprintf (&storage_s[11], time_format_s[this->c_code], TIME_VALUES);
  827.     break;
  828.   }
  829.   return storage_s;
  830. }
  831.  
  832.  
  833. // ascii_duration -- Returns the duration of time in an interval between this
  834. //                   object and some other date/time object
  835. // Input:            Reference to date/time object
  836. // Output:           Formatted char* string
  837.  
  838. const char* CoolDate_Time::ascii_duration (const CoolDate_Time& d) const {
  839.   static char storage_s[100];            // String to hold output
  840.   long n = ABS((this->time_seconds-d.time_seconds)); // Difference in seconds
  841.   long num_years = ABS((this->get_year() - d.get_year())); // Number years
  842.   long num_weeks = (n % YEAR) / WEEK;        // Number of weeks
  843.   long num_days = ((n % YEAR) % WEEK) / DAY;    // Number days
  844.   long num_hours = (((n % YEAR) % WEEK) % DAY) / HOUR; // Number hours
  845.   long num_minutes = ((((n % YEAR) % WEEK) % DAY) % HOUR) / MINUTE;
  846.   long num_seconds = (((((n % YEAR) % WEEK) % DAY) % HOUR) % MINUTE);
  847.   sprintf (storage_s,
  848.      "%ld years, %ld weeks, %ld days, %ld hours, %ld minutes, %ld seconds",
  849.       num_years, num_weeks, num_days, num_hours, num_minutes, num_seconds);
  850.   return storage_s;
  851. }
  852.  
  853.  
  854. // inrange -- Takes a char and returns a 1 if it is a digit between 0 and 9,
  855. //            returns 2 if it is a letter of the alphabet and returns 0
  856. //            otherwise.  This is used by parse to break things into tokens.
  857. //
  858. // Input   -- a char
  859. // Output  -- an int as described above.
  860.  
  861. int inrange (char c) {
  862.   if (isdigit (c))                // If character is a digit
  863.     return (1);                    // Return indication
  864.   if (isalpha (c))                // If character is a letter
  865.     return(2);                    // Return indication
  866.   else return(0);                // Else return failure
  867. }
  868.  
  869.  
  870. // getzone -- This looks for a valid time zone in the char*, if one is
  871. //            found the proper slots of the CoolDate_Time object are set and
  872. //            that part of the char* is deleted.
  873. //
  874. // Input   -- Takes a reference to a CoolDate_Time object, and a char*
  875. // Output  -- Does not return anything, just mutates the CoolDate_Time object.
  876.     
  877. void getzone (CoolDate_Time& d, char* s) {
  878.   c_upcase(s);
  879.   int ind = 0;
  880.   long start,end;
  881.   if (strfind(s,"*CANADA?EASTERN*",&start,&end)) {
  882.     d.tz_code = CANADA_EASTERN;
  883.     s = strnremove(s+start,end-start);
  884.   }
  885.   else if (strfind(s,"*CANADA?CENTRAL*",&start,&end)) {
  886.     d.tz_code = CANADA_CENTRAL;
  887.     s = strnremove(s+start,end-start);
  888.   }
  889.   else if (strfind(s,"*CANADA?MOUNTAIN*",&start,&end)) {
  890.     d.tz_code = CANADA_MOUNTAIN;
  891.     s = strnremove(s+start,end-start);
  892.   }
  893.   else if (strfind(s,"*CANADA?PACIFIC*",&start,&end)) {
  894.     d.tz_code = CANADA_PACIFIC;
  895.     s = strnremove(s+start,end-start);
  896.   }
  897.   else if (strfind(s,"*CANADA?YUKON*",&start,&end)) {
  898.     d.tz_code = CANADA_YUKON;
  899.     s = strnremove(s+start,end-start);
  900.   }
  901.   else if (strfind(s,"*EASTERN*",&start,&end) || strfind(s,"*EDT*",&start,&end)) {
  902.     d.tz_code = US_EASTERN;
  903.     s = strnremove(s+start,end-start);
  904.   }
  905.   else if (strfind(s,"*CENTRAL*",&start,&end) || strfind(s,"*CDT*",&start,&end)) {
  906.     d.tz_code = US_CENTRAL;
  907.     s = strnremove(s+start,end-start);
  908.   }
  909.   else if (strfind(s,"*MOUNTAIN*",&start,&end) || strfind(s,"*MDT*",&start,&end)) {
  910.     d.tz_code = US_MOUNTAIN;
  911.     s = strnremove(s+start,end-start);
  912.   }
  913.   else if (strfind(s,"*PACIFIC*",&start,&end)) {
  914.     d.tz_code = US_PACIFIC;
  915.     s = strnremove(s+start,end-start);
  916.   }
  917.   else if (strfind(s,"*PACIFIC?NEW*",&start,&end)) {
  918.     d.tz_code = US_PACIFIC_NEW;
  919.     s = strnremove(s+start,end-start);
  920.   }
  921.   else if (strfind(s,"*YUKON*",&start,&end)) {
  922.     d.tz_code = US_YUKON;
  923.     s = strnremove(s+start,end-start);
  924.   }
  925.   else if (strfind(s,"*EAST?INDIANA*",&start,&end)) {
  926.     d.tz_code = US_EAST_INDIANA;
  927.     s = strnremove(s+start,end-start);
  928.   }   
  929.   else if (strfind(s,"*ARIZONA*",&start,&end)) {
  930.     d.tz_code = US_ARIZONA;
  931.     s = strnremove(s+start,end-start);
  932.   }
  933.   else if (strfind(s,"*HAWAII*",&start,&end)) {
  934.     d.tz_code = US_HAWAII;
  935.     s = strnremove(s+start,end-start);
  936.   }
  937.   else if (strfind(s,"*NEWFOUNDLAND*",&start,&end)) {
  938.     d.tz_code = CANADA_NEWFOUNDLAND;
  939.     s = strnremove(s+start,end-start);
  940.   }
  941.   else if (strfind(s,"*ATLANTIC*",&start,&end)) {
  942.     d.tz_code = CANADA_ATLANTIC;
  943.     s = strnremove(s+start,end-start);
  944.   }
  945.   else if (strfind(s,"*SASKATCHEWAN*",&start,&end)) {
  946.     d.tz_code = CANADA_EAST_SASKATCHEWAN;
  947.     s = strnremove(s+start,end-start);
  948.   }
  949.   else if (strfind(s,"*EIRE*",&start,&end) || strfind(s,"*GMT*",&start,&end)) {
  950.     d.tz_code = GB_EIRE;
  951.     s = strnremove(s+start,end-start);
  952.   }
  953.   else if (strfind(s,"*WET*",&start,&end)) {
  954.     d.tz_code = WET;
  955.     s = strnremove(s+start,end-start);
  956.   }
  957.   else if (strfind(s,"*ICELAND*",&start,&end)) {
  958.     d.tz_code = ICELAND;
  959.     s = strnremove(s+start,end-start);
  960.   }
  961.   else if (strfind(s,"*MET*",&start,&end)) {
  962.     d.tz_code = MET;
  963.     s = strnremove(s+start,end-start);
  964.   }
  965.   else if (strfind(s,"*POLAND*",&start,&end)) {
  966.    d.tz_code = POLAND;
  967.    s = strnremove(s+start,end-start);
  968.   }
  969.   else if (strfind(s,"*EET*",&start,&end)) {
  970.     d.tz_code = EET;
  971.     s = strnremove(s+start,end-start);
  972.   }
  973.   else if (strfind(s,"*TURKEY*",&start,&end)) {
  974.     d.tz_code = TURKEY;
  975.     s = strnremove(s+start,end-start);
  976.   }
  977.   else if (strfind(s,"*W_SU*",&start,&end)) {
  978.     d.tz_code = W_SU;
  979.     s = strnremove(s+start,end-start);
  980.   }
  981.   else if (strfind(s,"*PRC*",&start,&end)) {
  982.     d.tz_code = PRC;
  983.     s = strnremove(s+start,end-start);
  984.   }
  985.   else if (strfind(s,"*KOREA*",&start,&end)) {
  986.     d.tz_code = KOREA;
  987.     s = strnremove(s+start,end-start);
  988.   }
  989.   else if (strfind(s,"*JAPAN*",&start,&end)) {
  990.    d.tz_code = JAPAN;
  991.     s = strnremove(s+start,end-start);   
  992.   }
  993.   else if (strfind(s,"*SINGAPORE*",&start,&end)) {
  994.     d.tz_code = SINGAPORE;
  995.     s = strnremove(s+start,end-start);
  996.   }
  997.   else if (strfind(s,"*HONGKONG*",&start,&end)) {
  998.     d.tz_code = HONGKONG;
  999.     s = strnremove(s+start,end-start);
  1000.   }
  1001.   else if (strfind(s,"*ROC*",&start,&end)) {
  1002.     d.tz_code = ROC;
  1003.     s = strnremove(s+start,end-start);
  1004.   }
  1005.   else if (strfind(s,"*TASMANIA*",&start,&end)) {
  1006.     d.tz_code = AUSTRALIA_TASMANIA;
  1007.     s = strnremove(s+start,end-start);
  1008.   }
  1009.   else if (strfind(s,"*QUEENSLAND*",&start,&end)) {
  1010.     d.tz_code = AUSTRALIA_QUEENSLAND;
  1011.     s = strnremove(s+start,end-start);
  1012.   }
  1013.   else if (strfind(s,"*NORTH*",&start,&end)) {
  1014.    d.tz_code = AUSTRALIA_NORTH;
  1015.    s = strnremove(s+start,end-start);
  1016.   }
  1017.   else if (strfind(s,"*WEST*",&start,&end)) {
  1018.    d.tz_code = AUSTRALIA_WEST;
  1019.    s = strnremove(s+start,end-start);
  1020.   }
  1021.   else if (strfind(s,"*SOUTH*",&start,&end)) {
  1022.    d.tz_code = AUSTRALIA_SOUTH;
  1023.    s = strnremove(s+start,end-start);
  1024.   }
  1025.   else if (strfind(s,"*VICTORIA*",&start,&end)) {
  1026.    d.tz_code = AUSTRALIA_VICTORIA;
  1027.    s = strnremove(s+start,end-start);
  1028.   }
  1029.   else if (strfind(s,"*NSW*",&start,&end)) {
  1030.    d.tz_code = AUSTRALIA_NSW;
  1031.    s = strnremove(s+start,end-start);
  1032.   }
  1033.   else if (strfind(s,"*NZ*",&start,&end)) {
  1034.    d.tz_code = NZ;
  1035.    s = strnremove(s+start,end-start);
  1036.   }
  1037. }
  1038.  
  1039.  
  1040. #define TOKEN_LIMIT 16
  1041.  
  1042.  
  1043. // parse  -- This is the CoolDate_Time parser, it is a member function.  It parses
  1044. //           the time and date out of the given char*, source, and sets all 
  1045. //           the appropriate slots of *this to the proper values.  If the 
  1046. //           optional argument settz is true, then the getzone function above
  1047. //           is called and searches for a timezone.
  1048. // Input  -- A char* source, and an optional int settz whose defalut is zero.
  1049. // Output -- Nothing is returned, the object is modified.
  1050.  
  1051. void CoolDate_Time::parse (char* source, int settz) {
  1052.   const char* m;
  1053.   int token_num[TOKEN_LIMIT];
  1054.   int token_alph[TOKEN_LIMIT];
  1055.   int token_used[TOKEN_LIMIT];
  1056.   CoolString token_list[TOKEN_LIMIT];
  1057.   int tcount = 0;
  1058.   token_alph[0] = 0;
  1059.   token_num[0] = 0;
  1060.   int flag = 0;
  1061.   int ind;
  1062.   long year = -1;
  1063.   int month = -1;
  1064.   int day = -1;
  1065.   int hour = -1;
  1066.   int minute = -1;
  1067.   int second = -1;
  1068.  
  1069.   if (settz) getzone(*this,source);
  1070.   int len = (int)strlen(source);
  1071.  
  1072.   //////////////////////////////////////////////////////////////////////
  1073.   //
  1074.   // This part of the parser breaks source down into tokens.
  1075.   // 
  1076.   //////////////////////////////////////////////////////////////////////
  1077.  
  1078.   for (ind = 0; ind < TOKEN_LIMIT; ind++)
  1079.     token_num[ind] = 0;
  1080.   for (ind = 0; ind < TOKEN_LIMIT; ind++)
  1081.     token_alph[ind] = 0;
  1082.   for (ind = 0; ind < TOKEN_LIMIT; ind++)
  1083.     token_used[ind] = 0;
  1084.   
  1085.   for (ind=0; ind < len; ind++)
  1086.     switch (inrange(source[ind])) {
  1087.     case 1:
  1088.       flag = 1;
  1089.       token_list[tcount] += source[ind];
  1090.       token_num[tcount] = 1;
  1091.       break;
  1092.     case 2:
  1093.       flag = 1;
  1094.       token_list[tcount] += source[ind];
  1095.       token_alph[tcount] = 1;
  1096.       break;
  1097.     case 0:
  1098.       if (flag) {
  1099.     if (++tcount > TOKEN_LIMIT) {
  1100.       //Raise Error, SYM(CoolDate_Time), SYM(Too_Many_Tokens),
  1101.       printf ("CoolDate_Time::parse(): More than %d tokens in input.\n",
  1102.           TOKEN_LIMIT);
  1103.           abort ();
  1104.         }
  1105.     token_alph[tcount] = 0;
  1106.     token_num[tcount] = 0;
  1107.       }
  1108.       flag = 0;
  1109.       break;
  1110.     }
  1111.   if (flag == 0) tcount--; 
  1112.   if (tcount <= 0) {
  1113.     //Raise Error, SYM(CoolDate_Time), SYM(Too_Few_Tokens),
  1114.     printf ("CoolDate_Time::parse(): Not enough tokens in input.\n");
  1115.     abort ();
  1116.   }
  1117.  
  1118.   //////////////////////////////////////////////////////////////////////
  1119.   //
  1120.   // This part of the parser checks for spelled out months, and converts
  1121.   // them to integer representations.
  1122.   // 
  1123.   //////////////////////////////////////////////////////////////////////
  1124.   
  1125.   for (ind=0; ind<=tcount; ind++)
  1126.     if (token_num[ind] == 0 && token_alph[ind] == 1) {
  1127.       m = upcase(token_list[ind]);
  1128.       if (0 == strcmp(m,"JAN") || 0 == strcmp(m,"JANUARY")) {
  1129.     token_list[ind] = "01";
  1130.     token_num[ind] = 1;
  1131.     token_alph[ind] = 0;
  1132.       }
  1133.       else if (0 == strcmp(m,"FEB") || 0 == strcmp(m,"FEBRUARY")) {
  1134.     token_list[ind] = "02";
  1135.     token_num[ind] = 1;
  1136.     token_alph[ind] = 0;
  1137.       }
  1138.       else if (0 == strcmp(m,"MAR") || 0 == strcmp(m,"MARCH")) {
  1139.     token_list[ind] = "03";
  1140.     token_num[ind] = 1;
  1141.     token_alph[ind] = 0;
  1142.       }
  1143.       else if (0 == strcmp(m,"APR") || 0 == strcmp(m,"APRIL")) {
  1144.     token_list[ind] = "04";
  1145.     token_num[ind] = 1;
  1146.     token_alph[ind] = 0;
  1147.       }
  1148.       else if (0 == strcmp(m,"MAY")) {
  1149.     token_list[ind] = "05";
  1150.     token_num[ind] = 1;
  1151.     token_alph[ind] = 0;
  1152.       }
  1153.       else if (0 == strcmp(m,"JUN") || 0 == strcmp(m,"JUNE")) {
  1154.     token_list[ind] = "06";
  1155.     token_num[ind] = 1;
  1156.     token_alph[ind] = 0;
  1157.       }
  1158.       else if (0 == strcmp(m,"JUL") || 0 == strcmp(m,"JULY")) {
  1159.     token_list[ind] = "07";
  1160.     token_num[ind] = 1;
  1161.     token_alph[ind] = 0;
  1162.       }
  1163.       else if (0 == strcmp(m,"AUG") || 0 == strcmp(m,"AUGUST")) {
  1164.     token_list[ind] = "08";
  1165.     token_num[ind] = 1;
  1166.     token_alph[ind] = 0;
  1167.       }
  1168.       else if (0 == strcmp(m,"SEP") || 0 == strcmp(m,"SEPTEMBER")) {
  1169.     token_list[ind] = "09";
  1170.     token_num[ind] = 1;
  1171.     token_alph[ind] = 0;
  1172.       }
  1173.       else if (0 == strcmp(m,"OCT") || 0 == strcmp(m,"OCTOBER")) {
  1174.     token_list[ind] = "10";
  1175.     token_num[ind] = 1;
  1176.     token_alph[ind] = 0;
  1177.       }
  1178.       else if (0 == strcmp(m,"NOV") || 0 == strcmp(m,"NOVEMBER")) {
  1179.     token_list[ind] = "11";
  1180.     token_num[ind] = 1;
  1181.     token_alph[ind] = 0;
  1182.       }
  1183.       else if (0 == strcmp(m,"DEC") || 0 == strcmp(m,"DECEMBER")) {
  1184.     token_list[ind] = "12";
  1185.     token_num[ind] = 1;
  1186.     token_alph[ind] = 0;
  1187.       }
  1188.     }
  1189.  
  1190.   ////////////////////////////////////////////////////////////////////////
  1191.   //
  1192.   // LOOKS FOR A YEAR, AND TAKES THE APPROPRIATE THINGS AROUND IT TO 
  1193.   // FILL IN THE DATE SLOTS (year, month, day).
  1194.   //
  1195.   ////////////////////////////////////////////////////////////////////////
  1196.   
  1197.   int lngth;
  1198.   flag = -1;
  1199.   for(ind=0; ind <= tcount; ind++)
  1200.     if (token_num[ind] == 1 &&
  1201.     token_alph[ind] == 0 &&
  1202.     strlen(token_list[ind]) > 2 ||
  1203.      atoi(token_list[ind]) > 59) {
  1204.       flag = ind;
  1205.       break;
  1206.     }
  1207.   if (flag != -1) {
  1208.     year = atoi(token_list[flag]);
  1209.     token_used[flag]=1; 
  1210.     if (this->c_code==SWEDEN || this->c_code==FRENCH_CANADIAN) {
  1211.       for (++ind; token_num[ind] == 1 &&
  1212.        token_alph[ind] != 1 &&
  1213.        strlen(token_list[ind]) <= 2; ind++);
  1214.       ind = ind - flag -1;
  1215.       if (ind > 2) ind = 2;
  1216.       switch(ind){
  1217.       case 0:
  1218.     month = 1;
  1219.     day = 1;
  1220.       case 1:
  1221.     len = atoi(token_list[flag+1]);
  1222.     if (len > 31) {
  1223.       //Raise Error, SYM(CoolDate_Time), SYM(Unknown_Token),
  1224.       printf ("CoolDate_Time::parse(): Unrecognized token in input.\n");
  1225.       abort ();
  1226.         }
  1227.     token_used[flag+1] = 1;
  1228.     if (len > 12) {
  1229.       day = len;
  1230.       month = 1;
  1231.     }
  1232.     else {
  1233.       month = len;
  1234.       day = 1;
  1235.     }
  1236.       case 2:
  1237.     len = atoi(token_list[flag+1]);
  1238.     lngth = atoi(token_list[flag+2]);
  1239.     if (len > 31 || lngth > 31) {
  1240.       //Raise Error, SYM(CoolDate_Time), SYM(Unknown_Token),
  1241.       printf ("CoolDate_Time::parse(): Unrecognized token in input.\n");
  1242.       abort ();
  1243.         }
  1244.     token_used[flag+1] = 1;
  1245.     if (len<13 && lngth>12) {
  1246.       day = lngth;
  1247.       month = len;
  1248.       token_used[flag+2] = 1;
  1249.     }
  1250.     else {
  1251.       day = len;
  1252.       if (lngth>12) month = 1;
  1253.       else {
  1254.         month=lngth;
  1255.         token_used[flag+2] = 1;
  1256.       }
  1257.     }
  1258.       }
  1259.     }
  1260.     else {
  1261.       for (--ind; 0 <= ind && token_num[ind] == 1 &&
  1262.        token_alph[ind] != 1 &&
  1263.        strlen(token_list[ind]) <= 2; ind--);
  1264.       ind = flag - ind - 1;
  1265.       if (ind>2) ind=2;
  1266.       switch(ind){
  1267.       case 0:
  1268.     month = 1;
  1269.     day = 1;
  1270.     break;
  1271.       case 1:
  1272.     len = atoi(token_list[flag-1]);
  1273.     if (len > 31) {
  1274.       //Raise Error, SYM(CoolDate_Time), SYM(Unknown_Token),
  1275.       printf ("CoolDate_Time::parse(): Unrecognized token in input.\n");
  1276.       abort ();
  1277.         }
  1278.     token_used[flag-1] = 1;
  1279.     if (len>12) {
  1280.       day = len;
  1281.       month = 1;
  1282.     }
  1283.     else {
  1284.       month = len;
  1285.       day = 1;
  1286.     }
  1287.     break;
  1288.       case 2:
  1289.     len = atoi(token_list[flag-1]);
  1290.     lngth = atoi(token_list[flag-2]);
  1291.     if (len > 31 || lngth > 31) {
  1292.       //Raise Error, SYM(CoolDate_Time), SYM(Unknown_Token),
  1293.       printf ("CoolDate_Time::parse(): Unrecognized token in input.\n");
  1294.       abort ();
  1295.         }
  1296.     if (this->c_code != UNITED_KINGDOM) {
  1297.       token_used[flag-1] = 1;
  1298.       if (len < 13 && lngth > 12) {
  1299.         day = lngth;
  1300.         month = len;
  1301.         token_used[flag-2] = 1;
  1302.       }
  1303.       else {
  1304.         day = len;
  1305.         if (lngth>12) month = 1;
  1306.         else {
  1307.           month=lngth;
  1308.           token_used[flag-2] = 1;
  1309.         }
  1310.       }
  1311.     }
  1312.     else {
  1313.       token_used[flag-2] = 1;
  1314.       if (lngth < 13 && len > 12) {
  1315.         day = len;
  1316.         month = lngth;
  1317.         token_used[flag-1] = 1;
  1318.       }
  1319.       else {
  1320.         day = lngth;
  1321.         if (len>12) month = 1;
  1322.         else {
  1323.           month=len;
  1324.         token_used[flag-1] = 1;
  1325.         }
  1326.       }
  1327.     }
  1328.     break;
  1329.       }
  1330.     }
  1331.   }
  1332.  
  1333.   ////////////////////////////////////////////////////////////////////////
  1334.   //
  1335.   // LOOKS FOR AN "AM" OR "PM" AND TAKES EVERY APROPRIATE TOKEN BEFORE 
  1336.   // THE "AM" OR "PM" TO FILL THE TIME SLOTS (hour, minute, second).
  1337.   //
  1338.   ////////////////////////////////////////////////////////////////////////
  1339.  
  1340.   int btrack;
  1341.   long start, end;
  1342.   for (ind = 0; ind <= tcount; ind++) 
  1343.     if (token_alph[ind] == 1) {
  1344.       flag = 0;
  1345.       m = upcase(token_list[ind]);
  1346.       if (strrfind(m, "*PM*", &start, &end) ||
  1347.       strrfind(m, "*AM*", &start, &end) ) { 
  1348.     
  1349.     if (token_list[ind][start] == 'P') flag=1;    
  1350.     btrack = token_num[ind];
  1351.     len = (int)strlen(token_list[ind]);
  1352.     
  1353.     if (btrack && (token_list[ind][len-1] != 'M' || len > 4 || len < 3)) {
  1354.       //Raise Error, SYM(CoolDate_Time), SYM(Invalid_Time),
  1355.       printf ("CoolDate_Time::parse(): Invalid time specified in input.\n");
  1356.       abort ();
  1357.         }
  1358.     if (btrack==0 && len != 2) {
  1359.       //Raise Error, SYM(CoolDate_Time), SYM(Invalid_Time),
  1360.       printf ("CoolDate_Time::parse(): Invalid time specified in input.\n");
  1361.       abort ();
  1362.         }
  1363.     for (int tmp = ind-1; 0 <= tmp && token_num[tmp] != 0 
  1364.          && strlen(token_list[tmp]) <= 2
  1365.          && token_used[tmp] != 1; tmp--);
  1366.     tmp = ind - tmp - 1;
  1367.     if (btrack) tmp++;
  1368.     if (tmp>3) tmp = 3;
  1369.     // This case if part of the time is in the same token as the
  1370.     // "am" or "pm".
  1371.  
  1372.     if (btrack)    // PM/AM and number in one token
  1373.       switch(tmp) {
  1374.       case 1:
  1375.         hour = atoi(token_list[ind]);
  1376.         if (hour > 23) {
  1377.           //Raise Error, SYM(CoolDate_Time), SYM(Invalid_Hour),
  1378.           printf ("CoolDate_Time::parse(): Specified hour out of range.\n");
  1379.           abort ();
  1380.             }
  1381.         if (flag && hour<12) hour += 12;
  1382.         token_used[ind] = 1;
  1383.         minute = 0;
  1384.         second = 0;
  1385.         break;
  1386.       case 2:
  1387.         hour = atoi(token_list[ind-1]);
  1388.         if (hour > 23) {
  1389.           //Raise Error, SYM(CoolDate_Time), SYM(Invalid_Hour),
  1390.           printf ("CoolDate_Time::parse(): Specified hour out of range.\n");
  1391.           abort ();
  1392.             }
  1393.         if (flag && hour<12) hour += 12;
  1394.         minute = atoi(token_list[ind]);
  1395.         if (minute > 59) {
  1396.           //Raise Error, SYM(CoolDate_Time), SYM(Invalid_Minutes),
  1397.           printf ("CoolDate_Time::parse(): Specified minutes out of range.\n");
  1398.           abort ();
  1399.             }
  1400.         token_used[ind] = 1;
  1401.         token_used[ind-1] = 1;
  1402.         second = 0;
  1403.         break;
  1404.       case 3:
  1405.         hour = atoi(token_list[ind-2]);
  1406.         if (hour > 23) {
  1407.           //Raise Error, SYM(CoolDate_Time), SYM(Invalid_Hour),
  1408.           printf ("CoolDate_Time::parse(): Specified hour out of range.\n");
  1409.           abort ();
  1410.             }
  1411.         if (flag && hour<12) hour += 12;
  1412.         minute = atoi(token_list[ind-1]);
  1413.         if (minute > 59) {
  1414.           //Raise Error, SYM(CoolDate_Time), SYM(Invalid_Minutes),
  1415.           printf ("CoolDate_Time::parse(): Specified minutes out of range.\n");
  1416.           abort ();
  1417.             }
  1418.         second = atoi(token_list[ind]);
  1419.         if (second > 59) {
  1420.           //Raise Error, SYM(CoolDate_Time), SYM(Invalid_Seconds),
  1421.           printf ("CoolDate_Time::parse(): Specified seconds out of range.\n");
  1422.           abort ();
  1423.             }
  1424.         token_used[ind] = 1;
  1425.         token_used[ind-1] = 1;
  1426.         token_used[ind-2] = 1;
  1427.         break;
  1428.       }
  1429.  
  1430.     else
  1431.     
  1432.       switch(tmp) {
  1433.       case 0: 
  1434.         minute = 0;
  1435.         second = 0;
  1436.         if (flag) hour=12; 
  1437.         else hour=0; 
  1438.         break;
  1439.       case 1:
  1440.         hour = atoi(token_list[ind-1]);
  1441.         token_used[ind-1] = 1;
  1442.         if (hour > 23) {
  1443.           //Raise Error, SYM(CoolDate_Time), SYM(Invalid_Hour),
  1444.           printf ("CoolDate_Time::parse(): Specified hour out of range.\n");
  1445.           abort ();
  1446.             }
  1447.         if (flag && hour < 12) hour += 12;
  1448.         minute = 0;
  1449.         second = 0;
  1450.         break;
  1451.       case 2:
  1452.         hour = atoi(token_list[ind-2]);
  1453.         if (hour > 23) {
  1454.           //Raise Error, SYM(CoolDate_Time), SYM(Invalid_Hour),
  1455.           printf ("CoolDate_Time::parse(): Specified hour out of range.\n");
  1456.           abort ();
  1457.             }
  1458.         if (flag && hour < 12) hour += 12;
  1459.         minute = atoi(token_list[ind-1]);
  1460.         if (minute > 59) {
  1461.           //Raise Error, SYM(CoolDate_Time), SYM(Invalid_Minutes),
  1462.           printf ("CoolDate_Time::parse(): Specified minutes out of range.\n");
  1463.           abort ();
  1464.             }
  1465.         token_used[ind-1] = 1;
  1466.         token_used[ind-2] = 1;
  1467.         second=0;
  1468.         break;
  1469.       case 3:
  1470.         hour = atoi(token_list[ind-3]);
  1471.         if (hour > 23) {
  1472.           //Raise Error, SYM(CoolDate_Time), SYM(Invalid_Hour),
  1473.           printf ("CoolDate_Time::parse(): Specified hour out of range.\n");
  1474.           abort ();
  1475.             }
  1476.         if (flag && hour < 12) hour += 12;
  1477.         minute = atoi(token_list[ind-2]);
  1478.         if (minute > 59) {
  1479.           //Raise Error, SYM(CoolDate_Time), SYM(Invalid_Minutes),
  1480.           printf ("CoolDate_Time::parse(): Specified minutes out of range.\n");
  1481.           abort ();
  1482.             }
  1483.         second = atoi(token_list[ind-1]);
  1484.         if (second > 59) {
  1485.           //Raise Error, SYM(CoolDate_Time), SYM(Invalid_Seconds),
  1486.           printf ("CoolDate_Time::parse(): Specified seconds out of range.\n");
  1487.           abort ();
  1488.             }
  1489.         token_used[ind-1] = 1;
  1490.         token_used[ind-2] = 1;
  1491.         token_used[ind-3] = 1;
  1492.         break;
  1493.       }
  1494.     break;
  1495.       }
  1496.     }
  1497.  
  1498.   ////////////////////////////////////////////////////////////////////////
  1499.   //
  1500.   // This part of the parser fills in any remaining slots not filled 
  1501.   // above, and sets the rest to defaults.
  1502.   //
  1503.   ////////////////////////////////////////////////////////////////////////
  1504.  
  1505.   CoolDate_Time current;
  1506.   current.set_local_time();
  1507.   int first = -1;
  1508.   int secnd = -1;
  1509.  
  1510.   if (year == -1) {
  1511.     int sind, find;
  1512.     for (ind = 0; ind <= tcount; ind++) 
  1513.        if (token_num[ind] != 0 
  1514.            && token_alph[ind] == 0
  1515.            && strlen(token_list[ind]) <= 2
  1516.            && token_used[ind] != 1) {
  1517.          if (first != -1) {                    
  1518.            secnd = atoi(token_list[ind]);
  1519.            sind = ind;
  1520.            token_used[ind] = 1;
  1521.            break;
  1522.          }
  1523.          first = atoi(token_list[ind]);
  1524.          find = ind;
  1525.          token_used[ind] = 1;
  1526.            }
  1527.   
  1528.     if (first != -1 && first <= 31){
  1529.       if (this->c_code != UNITED_KINGDOM) {
  1530.     if (secnd == -1 || secnd > 31) day = first;
  1531.     else {
  1532.       if (first > 12 && secnd > 12) {
  1533.         day = first;
  1534.         token_used[sind] = 0;
  1535.       }
  1536.       else {
  1537.         if (first <= 12){
  1538.           month = first;
  1539.           day = secnd;
  1540.         }
  1541.         else 
  1542.           if (secnd <= 12) { 
  1543.         month = secnd;
  1544.         day = first;
  1545.           }
  1546.       }
  1547.     }
  1548.       }
  1549.       else {
  1550.     if (secnd==-1 || secnd>31) day = first;
  1551.     else {
  1552.       if (first>12 && secnd>12) {
  1553.         day = secnd;
  1554.         token_used[find] = 0;
  1555.       }
  1556.       else {
  1557.         if (secnd <= 12){
  1558.           month = secnd;
  1559.           day = first;
  1560.         }
  1561.         else 
  1562.           if (first <= 12) { 
  1563.         month = first;
  1564.         day = secnd;
  1565.           }
  1566.       }
  1567.     }
  1568.       }
  1569.     }
  1570.     if (year == -1) year = current.get_year();
  1571.     if (month == -1) month = current.get_mon() + 1;
  1572.     if (day == -1) day = current.get_mday();
  1573.   }
  1574.  
  1575.   // THIS PART DEALS WITH PARTS OF THE TIME NOT ALREADY FILLED IN
  1576.  
  1577.   if (hour == -1) {
  1578.     first = -1;
  1579.     secnd = -1;
  1580.     int third = -1;
  1581.     for (ind=0; ind<=tcount; ind++) 
  1582.       if (token_num[ind] != 0 
  1583.       && token_alph[ind] == 0
  1584.       && strlen(token_list[ind]) <= 2
  1585.       && token_used[ind] != 1) {
  1586.       
  1587.         if (secnd != -1) {
  1588.           third = atoi(token_list[ind]);
  1589.           break;
  1590.         }
  1591.         if (first != -1)
  1592.           secnd = atoi(token_list[ind]);
  1593.         else 
  1594.           first = atoi(token_list[ind]);
  1595.       }
  1596.     if (third != -1) {
  1597.       second = third;
  1598.       if (second > 59) {
  1599.     printf ("CoolDate_Time::parse(): Specified seconds out of range.\n");
  1600.     abort ();
  1601.       }
  1602.     }
  1603.     if (secnd != -1) {
  1604.       minute = secnd;
  1605.       if (minute > 59) {
  1606.     printf ("CoolDate_Time::parse(): Specified minutes out of range.\n");
  1607.     abort ();
  1608.       }
  1609.     }
  1610.     if (first != -1) {
  1611.       hour = first;
  1612.       if (hour > 23) {
  1613.     printf ("CoolDate_Time::parse(): Specified hour out of range.\n");
  1614.     abort ();
  1615.       }
  1616.     }
  1617.   }
  1618.   if (hour == -1) hour = 0;
  1619.   if (minute == -1) minute = 0;
  1620.   if (second == -1) second = 0;
  1621.  
  1622.   //////////////////////////////////////////////////////////////////////
  1623.   //
  1624.   // DO SOME FINAL BOUNDS CHECKING AND SET THE SLOTS OF OBJ 
  1625.   // TO THE CORRECT VALUES
  1626.   //
  1627.   //////////////////////////////////////////////////////////////////////
  1628.  
  1629.   this->adjust_year(year);
  1630.   month--;
  1631.   if (year > 99) {
  1632.     this->century = int((year / 100) * 100);
  1633.     year -= this->century;
  1634.   }
  1635.   else
  1636.     this->century = 1900;
  1637.   if ((month == 0 || month == 2 || month == 4 || month == 6 || month == 7 ||
  1638.        month == 9 || month == 11) && day > 31) {
  1639.     printf ("CoolDate_Time::parse(): Too many days for month of %s.\n",
  1640.         month_names[month]);
  1641.     abort ();
  1642.   }
  1643.   else if ((month == 3 || month == 5 || month == 8 || month == 10)
  1644.        && day > 30) {
  1645.     printf ("CoolDate_Time::parse(): Too many days for month of %s.\n",
  1646.         month_names[month]);
  1647.     abort ();
  1648.   }
  1649.   else if (month == 1 && day > 28) 
  1650.     if (IS_LEAP_YEAR(year) && day < 30) ;
  1651.     else {
  1652.       printf ("CoolDate_Time::parse(): Too many days for month of %s.\n", 
  1653.           month_names[month]);
  1654.       abort ();
  1655.     }
  1656.  
  1657.    tm t;
  1658.    t.tm_sec = second;            // Copy seconds value
  1659.    t.tm_min = minute;            // Copy minutes value
  1660.    t.tm_hour = hour;            // Copy hours value
  1661.    t.tm_mday = day;            // Copy day of month value
  1662.    t.tm_mon = month;            // Copy month value
  1663.    t.tm_year = (int)year;        // Copy year value
  1664.    t.tm_isdst = 0;
  1665.  
  1666.    this->time_seconds = mktime (&t);
  1667.  
  1668.    if (this->time_seconds == -1)
  1669.      // Note: DOS returns -1 for any year prior to 1980
  1670.      this->time_seconds = time((long*)0);
  1671.    
  1672. #if defined(DOS)
  1673.   // OS2 mktime increments the hour by one if daylight savings time is in effect
  1674.   // we have to roll everything back one to correct for this.
  1675.    adjust_dst(&t);
  1676. #endif
  1677.  
  1678.    this->dt.tm_sec = t.tm_sec;            // Copy seconds value
  1679.    this->dt.tm_min = t.tm_min;            // Copy minutes value
  1680.    this->dt.tm_hour = t.tm_hour;        // Copy hours value
  1681.    this->dt.tm_mday = t.tm_mday;        // Copy day of month value
  1682.    this->dt.tm_mon = t.tm_mon;            // Copy month value
  1683.    this->dt.tm_year = t.tm_year;        // Copy year value
  1684.    this->dt.tm_wday = t.tm_wday;        // Copy day of week value
  1685.    this->dt.tm_yday = t.tm_yday;        // Copy day of year value
  1686.    this->dt.tm_isdst = t.tm_isdst;        // Copy day light savings flag
  1687. }
  1688.  
  1689.  
  1690. // operator<< -- Output CoolDate_Time object to output stream
  1691. // Input:        Output stream reference, CoolDate_Time reference
  1692. // Output:       Output stream reference
  1693.  
  1694. ostream& operator<< (ostream& os, const CoolDate_Time& d) {
  1695.   return os << country_names[d.c_code] << " " << d.ascii_date_time ();
  1696. }
  1697.  
  1698.